<?php
/**
 * Created by PhpStorm.
 * User: zgh
 * Date: 2022-01-20
 * Time: 14:32
 */

namespace app\common\item;

use app\common\exception\ServiceException;

class BaseItemLoader
{
    #最后的数据形式
    protected $item = [];


    protected $filter_fields_in = ""; //需要过滤的字段

    protected $filter_fields_out = ""; //过滤输出


    protected $validate = [];//验证数组


    protected $where = [];//where load出来的数组

    protected $where_alias = ""; //执行where alias

    protected $auto_field = [];

    const PROCESS_IN = 1;  //管道模式 1 代表执行 In
    const PROCESS_OUT = 2; //管道模式 2 代表执行 out
    const PROCESS_ALL = 3; //管道模式 3 代表执行全部

    protected $process_mode = 1; //

    protected $method_prefix_in = "_in";

    protected $method_prefix_out = "_out";

    //执行validate 方法
    protected function validate()
    {

    }

    public function addAutoField($field, $default = "")
    {
        if(!isset($this->item[$field])){
            $this->item[$field] = $default;
        }
        return $this;
    }

    public function clear()
    {
        $this->clearItem();
        $this->clearWhere();
        $this->clearValidate();
        return $this;
    }

    public function clearValidate()
    {
        $this->validate = [];
        return $this;
    }

    public function addFilterIn($fields)
    {
        $this->filter_fields_in = $fields;
        return $this;
    }

    public function addFilterOut($fields)
    {
        $this->filter_fields_out = $fields;
        return $this;
    }

    protected function filterData($is_filter, $filter_fields)
    {

        if (!is_array($filter_fields)) {
            $filter_fields = explode(",", $filter_fields);
        }
        foreach ($this->item as $key => $value) {
            if (!($is_filter ^ in_array($key, $filter_fields))) {
                unset($this->item[$key]);
            }
        }
    }


    public function addVal($key, $val = "")
    {
        if (is_array($key)) {
            $this->item = array_merge($this->item, $key);
        } else {
            $this->item = array_merge($this->item, [$key => $val]);
        }
        return $this;
    }

    protected function process_in()
    {
        $item = $this->item;
        if ($item && ($this->process_mode == self::PROCESS_IN || $this->process_mode == self::PROCESS_ALL)) {
            foreach ($item as $key => $row) {
                $method = $key . $this->method_prefix_in;
                if (method_exists($this, $method)) {
                    $value = $this->$method($row);
                    $item[$key] = $value;
                }
            }
            $this->item = $item;
        }
        return $this;
    }


    protected function process_out()
    {
        $item = $this->item;
        if ($item && ($this->process_mode == self::PROCESS_OUT || $this->process_mode == self::PROCESS_ALL)) {
            foreach ($item as $key => $row) {
                $method = $key . $this->method_prefix_out;
                if (method_exists($this, $method)) {
                    $value = $this->$method($row);
                    $item[$key] = $value;
                }
            }
            $this->item = $item;
        }
        return $this;
    }


    public function loadItem($mode = "")
    {
        if (is_numeric($mode)) {
            $this->process_mode = $mode;
        }
        $this->start(); //先执行 start 函数
        if (!empty($this->filter_fields_in)) {
            $is_filter = !(strrpos($this->filter_fields_in, "^") !== false);
            $filter_fields = str_replace("^", "", $this->filter_fields_in);
            $this->filterData($is_filter, $filter_fields);;
        }
        $this->verify();
        $this->process_in();
        $this->process_out();
        //进行输入输出器的判断
        if (!empty($this->filter_fields_out)) {
            $is_filter = !(strrpos($this->filter_fields_out, "^") === false);
            $filter_fields = str_replace($this->filter_fields_out, "");
            $this->filterData($is_filter, $filter_fields);;
        }
        $this->end(); //执行end 函数
        return $this->item;
    }


    public function start()
    {

    }

    public function end()
    {
    }

    protected function verify()
    {
        $data = $this->item;
        if (!empty($this->validate)) {
            foreach ($this->validate as $row) {
                $reflect = new \ReflectionClass($row['class']);
                $validate = $reflect->newInstanceArgs();
                if (empty($row['scene'])) {
                    if (!$validate->check($data)) {
                        throw  new ServiceException($validate->getError());
                    }
                } else {
                    //使用场景验证
                    if (!$validate->scene($row['scene'])->check($data)) {
                        throw  new ServiceException($validate->getError());
                    }
                }
            }
        }
        return $this;
    }


    public function addVerify($class, $scene = "")
    {
        $this->validate[] = [
            'class' => $class,
            'scene' => $scene
        ];
        return $this;
    }


    public function addWhereSearch($field, $type = 'str', $is_like = false, $is_force = false)
    {
        if (isset($this->item[$field])) {
            //继续判断类型
            $val = $this->item[$field];
            if ($type == 'str' && !$is_force && empty($val)) {
                return $this;
            } elseif ($type == 'int' && !$is_force && !is_numeric($val)) {
                return $this;
            }
        } else { //参数不存在
            if (!$is_force) { //不是要强行加 where
                return $this;
            }
            $val = "";
            if ($type == 'int') {
                $val = "0";
            }
        }
        if ($is_like) {
            $where = [$field, "like", "%" . $val . "%"];
        } else {
            $where = [$field, "=", $val];
        }
        $this->addWhere($where);
        return $this;
    }


    /**
     * 添加where 数组
     * @param $where
     * @return $this
     */
    public function addWhere($where)
    {
        //判断是否是关联数组
        if (count(array_filter(array_keys($where), 'is_string')) === 0) { //三维数组
            if (is_array($where[0])) { //判断是否是数组
                foreach ($where as $index => $row) {
                    $this->where[] = $row;
                }
            } else {
                $this->where[] = $where;
            }
        } else {
            foreach ($where as $key => $value) {
                $this->where[] = [$key, "=", $value];
            }
        }
        return $this;
    }

    /**
     * 清除where 数据
     * @return false
     */
    public function clearWhere()
    {
        $this->where = [];
        return false;
    }

    public function setMode($process_mode)
    {
        $this->process_mode = $process_mode;
        return $this;
    }

    /**
     * 清除item 数据
     */
    public function clearItem()
    {
        $this->item = [];
        return $this;
    }

    public function setWhereAlias($alias)
    {
        if (!empty($alias)) {
            $this->where_alias = $alias;
        }
        return $this;
    }

    /**
     * 加载出where数组
     */
    public function loadWhere()
    {
        $where = $this->where;
        //规定都是三维数组
        foreach ($where as &$item) {
            if (!empty($this->where_alias)) {
                $item[0] = $this->where_alias . "." . $item[0];
            }
        }
        return $where;
    }

}